﻿using System;
using Library.Collections.Generic;
using INDEX = System.UInt64;

namespace Library.Collections.Specialized
{
    public enum NotifyCollectionChangedAction
    {
        Add = 0,
        Remove = 1,
        Replace = 2,
        Move = 3,
        Reset = 4,
    }

    public class NotifyCollectionChangedEventArgs : EventArgs
    {
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly changedItems)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly newItems, IVectorReadOnly oldItems)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly changedItems, INDEX startingIndex)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, INDEX index)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly newItems, IVectorReadOnly oldItems, INDEX startingIndex)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly changedItems, INDEX index, INDEX oldIndex)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, INDEX index, INDEX oldIndex)
        {
            throw new NotImplementedException();
        }
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, INDEX index)
        {
            throw new NotImplementedException();
        }

        NotifyCollectionChangedAction action;
        IVectorReadOnly newItems;
        INDEX? newStartingIndex = null;
        IVectorReadOnly oldItems;
        INDEX? oldStartingIndex = null;

        public NotifyCollectionChangedAction Action { get { return action; } }
        public IVectorReadOnly NewItems { get { return newItems; } }
        public INDEX? NewStartingIndex { get { return newStartingIndex; } }
        public IVectorReadOnly OldItems { get { return oldItems; } }
        public INDEX? OldStartingIndex { get { return oldStartingIndex; } }
    }
    public class NotifyCollectionChangedEventArgs<T> : NotifyCollectionChangedEventArgs
    {
        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action)
            : base(action) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly<T> changedItems)
            : base(action, changedItems) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, T changedItem)
            : base(action, changedItem) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly<T> newItems, IVectorReadOnly<T> oldItems)
            : base(action, newItems, oldItems) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly<T> changedItems, INDEX startingIndex)
            : base(action, changedItems, startingIndex) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, T changedItem, INDEX index)
            : base(action, changedItem, index) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, T newItem, T oldItem)
            : base(action, newItem, oldItem) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly<T> newItems, IVectorReadOnly<T> oldItems, INDEX startingIndex)
            : base(action, newItems, oldItems, startingIndex) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IVectorReadOnly<T> changedItems, INDEX index, INDEX oldIndex)
            : base(action, changedItems, index, oldIndex) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, T changedItem, INDEX index, INDEX oldIndex)
            : base(action, changedItem, index, oldIndex) { }

        public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, T newItem, T oldItem, INDEX index)
            : base(action, newItem, oldItem, index) { }

        public new IVectorReadOnly<T> NewItems { get { return (IVectorReadOnly<T>)base.NewItems; } }
        public new IVectorReadOnly<T> OldItems { get { return (IVectorReadOnly<T>)base.OldItems; } }
    }

    public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs args);
    public delegate void NotifyCollectionChangedEventHandler<T>(object sender, NotifyCollectionChangedEventArgs<T> args);
    public delegate void NotifyCollectionChangingEventHandler(object sender, NotifyCollectionChangedEventArgs args);
    public delegate void NotifyCollectionChangingEventHandler<T>(object sender, NotifyCollectionChangedEventArgs<T> args);

    public interface INotifyCollectionChanging
    {
        event NotifyCollectionChangingEventHandler CollectionChanging;
    }
    public interface INotifyCollectionChanging<T> : INotifyCollectionChanging
    {
        new event NotifyCollectionChangingEventHandler<T> CollectionChanging;
    }

    public interface INotifyCollectionChanged
    {
        event NotifyCollectionChangedEventHandler CollectionChanged;
    }
    public interface INotifyCollectionChanged<T> : INotifyCollectionChanged
    {
        new event NotifyCollectionChangedEventHandler<T> CollectionChanged;
    }
}
